/*******************************************************************************
 * Copyright (c) 2011 TXT e-solutions SpA
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the research area ICT-2009.1.3
 * Internet of Things and enterprise environments.
 *
 *
 * Authors:
 *     Cristoforo Seccia (TXT e-solutions SpA)
 *
 * Contributors:
 *      Domenico Rotondi (TXT e-solutions SpA)
 *******************************************************************************/
package it.txt.access.capability.demo.soap.client.view;

import it.txt.access.capability.commons.schema.validation.CapabilitySchemaValidationHandler;
import it.txt.access.capability.commons.schema.validation.CapabilitySchemaValidationHandlerException;
import it.txt.access.capability.commons.utils.MessageUtils;
import it.txt.access.capability.commons.view.AccessRightsViewerDialog;
import it.txt.access.capability.factory.CapabilitySchemaFactoryException;
import it.txt.access.capability.demo.soap.client.sws.RequestClient;
import it.txt.access.capability.demo.soap.client.view.model.ServiceRequestCapabilityModel;
import it.txt.access.capability.demo.soap.client.view.model.UserKeystoreDataModel;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

/**
 *
 * @author Cristoforo Seccia (TXT e-solutions SpA)
 */
public class ClientGUIController implements WindowListener {

    private static final Logger LOGGER = Logger.getLogger(ClientGUIController.class.getName());
    private static final Cursor DEFAULT_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
    private static final Cursor BUSY_CURSOR = new Cursor(Cursor.WAIT_CURSOR);
    private ApplicationContext applicationContext;
    //The dialog used to view capability loaded by the user
    private AccessRightsViewerDialog capabilityViewerDialog;
    //The current capability file loaded by the user
    private File currentCapabilityFile = null;
    private RequestClient requestClient;
    //The capability gui form
    private ClientGUI clientGUI;

    public ClientGUIController() {
        initComponents();
    }

    private void initComponents() {
        clientGUI = new ClientGUI(this);
        applicationContext = new ClassPathXmlApplicationContext(
                "it/txt/access/capability/demo/soap/client/sws/applicationContext.xml");
        requestClient = applicationContext.getBean("capabilityClient", RequestClient.class);
    }

    public void createAndShowClient() {
        clientGUI.setDefaultCloseOperation(ClientGUI.DO_NOTHING_ON_CLOSE);
        clientGUI.addWindowListener(this);
        clientGUI.setVisible(true);
    }

    protected void setUserKeystoreData(UserKeystoreDataModel model) {
        String message;
        clientGUI.setCursor(BUSY_CURSOR);
        String title = "User Keystore data";
        try {
            ClientGUIControllerHelper.recoverUserDataX509Certificate(model);
            message = "Using User ID: " + model.getUserID();
            LOGGER.log(Level.INFO, message);
            showInfoMessage(clientGUI, title, message);
            clientGUI.appendLogMessage(MessageUtils.getInfoMessage(title, message));
        }
        catch (ClientGUIHelperException ex) {
            message = ex.getMessage();
            LOGGER.log(Level.SEVERE, message, ex);
            showErrorMessage(clientGUI, title, message);
            clientGUI.appendLogMessage(MessageUtils.getErrorMessage(title, message));
        }
        clientGUI.setCursor(DEFAULT_CURSOR);
    }

    protected ServiceRequestCapabilityModel setUserCapability(File userCapabilityFile) {
        ServiceRequestCapabilityModel result = null;
        clientGUI.setCursor(BUSY_CURSOR);
        String title = "Service Request Capability";
        try {
            currentCapabilityFile = userCapabilityFile;
            result = ClientGUIControllerHelper.loadUserCapability(currentCapabilityFile);
            clientGUI.appendLogMessage(MessageUtils.getInfoMessage(title,
                    "Using Capability - ID: " + result.getCapabilityID()));
        }
        catch(CapabilitySchemaFactoryException ex){
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex.getMessage());
            showErrorMessage(clientGUI, title, ex.getMessage());
            clientGUI.appendLogMessage(MessageUtils.getErrorMessage(title, ex.getMessage()));
        }
        catch(CapabilitySchemaValidationHandlerException ex){
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
            showErrorMessage(clientGUI, title, ex.getMessage());
            String errors = CapabilitySchemaValidationHandler.dumpValidationEvents(ex.getValidationEvents());
            clientGUI.appendLogMessage(MessageUtils.getErrorMessage(title, errors));
        }
        clientGUI.setCursor(DEFAULT_CURSOR);
        return result;
    }

    protected void viewUserCapability() {
        try {
            URI acceRightsUri = currentCapabilityFile.toURI();
            capabilityViewerDialog = new AccessRightsViewerDialog(acceRightsUri, clientGUI, true);
            capabilityViewerDialog.setLocationRelativeTo(clientGUI);
            capabilityViewerDialog.setVisible(true);
        } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
        } catch (SAXException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
        }
    }

    protected void sendUserCapabilityRequest(String resourceID, String operation) {
        //The signed request to send
        Element signedRequest = null;
        String title = "Service Request";
        try {
            //recover the capability signed request
            signedRequest = ClientGUIControllerHelper.createSignedCapabilityRequest(
                    resourceID, operation);
        }
        catch (ClientGUIHelperException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
            showErrorMessage(clientGUI, title, ex.getMessage());
            clientGUI.appendLogMessage(MessageUtils.getErrorMessage(title, ex.getMessage()));
            return;
        }
        String message = "Starting at: " + new Date().toString();
        LOGGER.log(Level.INFO, message);
        clientGUI.appendLogMessage(MessageUtils.getInfoMessage(title,message));
        clientGUI.capabilityRequestInProgress();        
        try {
            requestClient.userRequest(signedRequest);
        } catch (Exception ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
        }
    }

    protected void stopCapabilityRequest(){
    }

    protected static void showErrorMessage(Component parent, String title, String msg) {
        JOptionPane.showMessageDialog(parent, msg, title, JOptionPane.ERROR_MESSAGE);
    }

    protected static void showInfoMessage(Component parent, String title, String msg) {
        JOptionPane.showMessageDialog(parent, msg, title, JOptionPane.INFORMATION_MESSAGE);
    }

    private void stopClientAndCloseApplication() {
        stopCapabilityRequest();
        clientGUI.setVisible(false);
        LOGGER.log(Level.WARNING, "Return code (Finish: {0} - Cancel: {1} - Error: {2}): {3} ",
                new Object[]{ClientGUI.FINISH_RETURN_CODE, ClientGUI.CANCEL_RETURN_CODE,
                    ClientGUI.ERROR_RETURN_CODE, clientGUI.getReturnCode()});
        System.exit(0);
    }

    @Override
    public void windowClosing(WindowEvent e) {

        if (clientGUI.getReturnCode() == ClientGUI.FINISH_RETURN_CODE) {
            stopClientAndCloseApplication();
        }
        else{
            int resp = JOptionPane.showConfirmDialog(clientGUI,
                    "Are you sure you want to close?");
            if (resp == JOptionPane.YES_OPTION) {
                stopClientAndCloseApplication();
            }
        }
    }

    @Override
    public void windowOpened(WindowEvent e) {
    }

    @Override
    public void windowClosed(WindowEvent e) {
    }

    @Override
    public void windowIconified(WindowEvent e) {
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
    }

    @Override
    public void windowActivated(WindowEvent e) {
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
    }
}
